package cn.apotato.server.service.impl;

import cn.apotato.common.model.system.SysMenu;
import cn.apotato.modules.redis.service.RedisService;
import cn.apotato.server.mapper.SysMenuMapper;
import cn.apotato.server.service.SysMenuService;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.apotato.common.core.constant.SecurityConstants.PERMISSION_REDIS_KEY;

/**
 * 系统菜单服务impl
 *
 * @author 胡晓鹏
 * @date 2023/05/29
 */
@Slf4j
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Resource
    private RedisService redisService;

    /**
     * 保存批处理和忽视
     *
     * @param menuList 菜单列表
     */
    @Override
    public void saveBatchAndIgnore(Collection<SysMenu> menuList) {
        List<String> urlList = menuList.stream().map(SysMenu::getUrl).collect(Collectors.toList());
        if (CollUtil.isEmpty(urlList)) {
            return;
        }
        List<SysMenu> oldMenuList = this.lambdaQuery().in(SysMenu::getUrl, urlList).list();
        Map<String, SysMenu> oldMenuMap = oldMenuList.stream()
                .collect(Collectors.toMap(menu -> menu.getUrl() + ":" + menu.getRequestMethod(), menu -> menu));
        // 过滤掉已存在的数据
        menuList = menuList.stream()
                .filter(sysMenu -> oldMenuMap.get(sysMenu.getUrl() + ":" + sysMenu.getRequestMethod()) == null)
                .collect(Collectors.toList());
        if (CollUtil.isNotEmpty(menuList)) {
            this.saveBatch(menuList);
        }
    }

    /**
     * 创建
     *
     * @param entity 实体
     * @return {@link SysMenu}
     */
    @Override
    public SysMenu create(SysMenu entity) {
        log.info("create new menu for entity " + entity);
        if (entity == null) {
            log.info("entity is null, returning null");
            return null;
        }
        try {
            // 查询数据是否存在，存在则修改（只修改权限， 其他不做修改，保证前端用户修改后和系统权限修改后冲突。保证前端页面不能修改权限码）
            Long count = this.lambdaQuery()
                    .eq(SysMenu::getUrl, entity.getUrl())
                    .eq(SysMenu::getRequestMethod, entity.getRequestMethod())
                    .count();
            if (count > 0) {
                boolean update = this.lambdaUpdate()
                        // 只修改权限
                        .set(SysMenu::getPermission, entity.getPermission())
                        .eq(SysMenu::getUniqueId, entity.getUniqueId())
                        .update();
                if (!update) {
                    return null;
                }
            }else {
                if (!this.save(entity)) {
                    return null;
                }
            }
            // 处理子菜单
            List<SysMenu> children = entity.getChildren();
            if (CollUtil.isNotEmpty(children)) {
                children.forEach(child -> {
                    child.setParentId(entity.getId());
                });
                // 获取菜单唯一id
                List<Long> uniqueIdList = children.stream().map(SysMenu::getUniqueId).collect(Collectors.toList());
                // 查询数据库中已处在的权限
                List<SysMenu> oldSysMenuList = this.lambdaQuery().in(SysMenu::getUniqueId, uniqueIdList).list();
                // 不存在直接批量新增
                if (CollUtil.isEmpty(oldSysMenuList)) {
                    this.saveBatchAndIgnore(children);
                    return entity;
                }
                // 转换为key=uniqueId, value=SysMenu 的map集合
                Map<Long, SysMenu> oldMenuMap = oldSysMenuList.stream()
                        .collect(Collectors.toMap(SysMenu::getUniqueId, m -> m));
                // 新增
                List<SysMenu> saveSysMenuList = children.stream()
                        .filter(sysMenu -> oldMenuMap.get(sysMenu.getUniqueId()) == null)
                        .collect(Collectors.toList());
                if (CollUtil.isNotEmpty(saveSysMenuList)) {
                    this.saveBatch(saveSysMenuList);
                }
                // 修改
                List<SysMenu> updateSysMenuList = children.stream()
                        .filter(sysMenu -> oldMenuMap.get(sysMenu.getUniqueId()) != null)
                        .map(sysMenu -> {
                            SysMenu oldMenu = oldMenuMap.get(sysMenu.getUniqueId());
                            oldMenu.setPermission(sysMenu.getPermission());
                            return oldMenu;
                        })
                        .collect(Collectors.toList());
                if (CollUtil.isNotEmpty(updateSysMenuList)) {
                    this.updateBatchById(updateSysMenuList);
                }
            }
        }catch (Exception e) {
            log.error("e, {}", e.getMessage());
            // redis 没有事务，业务代码报错后手动将数据进行回滚
            redisService.pushMessage(PERMISSION_REDIS_KEY, entity);
            e.printStackTrace();
        }
        return entity;
    }
}
